/**
*  \file dtc.c
*
*  \brief
*   DTC API
*  \author nan.jiang@linde-china.com
*
*  \date  2020-03-06
* chang log 2020-4-3
    1. update below function,might be used for manual trigger dtc(not trigger by spv)
    dtcTrigger_Result kwp_dtc_trigger(U16 dtc_code,BO active);
    dtcTrigger_Result kwp_dtc_trigger_with_one_s16_extra(U16 dtc_code, BO active, S16 ext1);
    dtcTrigger_Result kwp_dtc_trigger_with_four_f32_extra(U16 dtc_code, BO active, F32 ext1,F32 ext2,F32 ext3, F32 ext4);
    dtcTrigger_Result kwp_dtc_trigger_with_fourS16_twoF32_extra(U16 dtc_code, BO active,S16 ext1_s16,S16 ext2_s16,F32 ext3_s16,F32 ext4_s16, F32 ext5_f32,F32 ext6_f32);
                                                                                                                                            
    2. change prototype requestStoreActiveCodeToHist_dsc prototype
    BO requestStoreActiveCodeToHist_dsc(const TDTCBuf *pinfo)
*/

/*===============================================[ private includes  ]================================================*/
#include "../kwpservices/kwpservices.h"
#include "../assertor/assertor.h"
#include "../endian/endian_read.h"
#include "../nvram/nvram.h"
#include "../app/app.h"
#include "dtc.h"
#include "../input/input.h"

/*===============================================[ private defines   ]================================================*/

/*===============================================[ private datatypes ]================================================*/
typedef struct {
   U16 dtc;
   U16 lcode;
   union
   {
       U16 buf16[8];
       /*F32 floatbuf[4];*/
   }store;
} __attribute__((__packed__)) TDTCBuf;
/*===============================================[ private functions ]================================================*/
static U8 loadHistoryDTC_Type0(void);
static U8 loadHistoryDTC_Type1(void);
static U8 loadHistoryDTC_Type2(void);
static void loadDtcHistoryInfomation(void);

/*===============================================[ public variables ]================================================*/
nv_readWriteparam*  const pDtcOperater  = (nv_readWriteparam* const)(ADDRESS_DTC_OPERATER);
nv_dtcCodelist*     const pDtcCodeList  = (nv_dtcCodelist* const)(ADDRESS_DTC_CODE_LIST);
nv_dtcStatusList*   const pDtcStatusList = (nv_dtcStatusList* const)(ADDRESS_DTC_STATUS_LIST);

/*===============================================[ private variables ]================================================*/
U16 activeDTCbuffer[ACTIVE_DTC_TOTAL_NUM] = {0};
U8  totalActive = 0;
U16 historyDtcBuffer_Type0[MAX_TOTAL_HISTORYDTC_TYPE0] = {0};
U16 historyDtcBuffer_Type1[MAX_TOTAL_HISTORYDTC_TYPE1] = {0};
U16 historyDtcBuffer_Type2[MAX_TOTAL_HISTORYDTC_TYPE2] = {0};
request_hist_dtc_st saveHistoryDtcRequestBuffer[DTC_HIST_REQ_BUF_SIZE];
U8  pushRequestIndex    = 0;
U8  popRequestIndex     = 0;
U8  RequestCount        = 0;
BO  flag_has_dtc_changes= FALSE;
BO  fDTCMaster = TRUE;
/*================================================[ inline functions ]================================================*/
extern S16 GetDTCInfo(S16 dtc, U16 *buf16, U32 *buf32);

/*================================================[ public functions ]================================================*/
activeDtcTrigger_Result activeDtcTrigger(U16 dtc_code,BO active)
{
    BO foundActive = FALSE;
    U8 foundActiveIndex = 0;

    BO foundIdle = FALSE;
    U8 	 foundIdleIndex = 0;

    activeDtcTrigger_Result result = ACTIVEDTC_NO_CHANGE;

    result = ACTIVEDTC_NO_CHANGE;
    foundActive = FALSE;
    foundActiveIndex = 0;
    foundIdle = FALSE;
    foundIdleIndex = 0;
    
    if(TRUE == Is_TrueOrFalse(active))
    {
        //check if exist
        U8 i;
        //U16 container;
        
        //found exist
        for (i= 0; i < ACTIVE_DTC_TOTAL_NUM;i++)
        {
            //container = activeDTCbuffer[i];
            if( Is_TrueOrFalse((activeDTCbuffer[i] & ACTIVE_MASK)) )
            {
                if(dtc_code == (activeDTCbuffer[i]&DTCCODE_MASK) )
                {
                    foundActive = TRUE;
                    //foundActiveIndex = i;
                    break;
                }
            }
            else if(!foundIdle)
            {
                foundIdle = TRUE;
                foundIdleIndex = i;
            }
			else
			{
				
			}
        }
        //IF NOT exist,found an idle to contain it
        if(!foundActive)
        {
            if(foundIdle)
            {
                if(totalActive < ACTIVE_DTC_TOTAL_NUM)
                {
                    activeDTCbuffer[foundIdleIndex] = dtc_code;
                    activeDTCbuffer[foundIdleIndex] |= ACTIVE_MASK;
                    ++totalActive;
                    result = ACTIVEDTC_ADD;             
                }
            }
        }
    }
    else
    {
        U8 i;
        //U16 container;
        
        for (i= 0; i < ACTIVE_DTC_TOTAL_NUM;i++)
        {
            //container = activeDTCbuffer[i];
            if( Is_TrueOrFalse((activeDTCbuffer[i]&ACTIVE_MASK)) )
            {
                if(dtc_code == (activeDTCbuffer[i]&DTCCODE_MASK) )
                {
                    foundActive = TRUE;
                    foundActiveIndex = i;
                    break;
                }
            }
        }

        if(foundActive)
        {
            if(totalActive > 0U)
            {
                activeDTCbuffer[foundActiveIndex] = 0;
                --totalActive;
                result = ACTIVEDTC_DECREASE;                
            }
        }
    }
    
    return result;
}

BO requestStoreActiveCodeToHist_dsc(const TDTCBuf *pinfo)
{
	BO ret = FALSE;
	
    if(RequestCount < DTC_HIST_REQ_BUF_SIZE)
    {
        if(!pinfo)
        {
            saveHistoryDtcRequestBuffer[(pushRequestIndex)%DTC_HIST_REQ_BUF_SIZE].DTC       = 0;
            saveHistoryDtcRequestBuffer[(pushRequestIndex)%DTC_HIST_REQ_BUF_SIZE].Length    = 0;
        }
        else
        {
            saveHistoryDtcRequestBuffer[(pushRequestIndex)%DTC_HIST_REQ_BUF_SIZE].DTC = (*pinfo).dtc;
            saveHistoryDtcRequestBuffer[(pushRequestIndex)%DTC_HIST_REQ_BUF_SIZE].Length = (*pinfo).lcode;          
        }
        saveHistoryDtcRequestBuffer[(pushRequestIndex)%DTC_HIST_REQ_BUF_SIZE].DTC |= ACTIVE_MASK;

        U8 copy_index = 0;
        for(copy_index = 0;copy_index < (DTC_TYPE2_EXTRA_SIZE/2U);copy_index++)
        /*history DTC*/
        {
            if(NULL != pinfo)
            {
                saveHistoryDtcRequestBuffer[(pushRequestIndex+DTC_HIST_REQ_BUF_SIZE)%DTC_HIST_REQ_BUF_SIZE].ExtraData[copy_index] = (*pinfo).store.buf16[copy_index];
            }
            else
            {
                saveHistoryDtcRequestBuffer[(pushRequestIndex+DTC_HIST_REQ_BUF_SIZE)%DTC_HIST_REQ_BUF_SIZE].ExtraData[copy_index] = 0;
            }
            
        }
        pushRequestIndex = (pushRequestIndex+1U)%DTC_HIST_REQ_BUF_SIZE;

        ++RequestCount;
        ret = TRUE;
    }

    return ret;
}


/** gather information about a DTC and queue it for writing */
static void QPostDTC(U16 dtc)
{
  U16 d;
  
  d = dtc & DTC_DTCMASK;

  /* don't store DTCs if we are in passivemode or DTC-CODE < 100 or  DTC-CODE < 999 */
  if( Is_TrueOrFalse( (DTC_DONTSTORE())) 
  	||(d < DTC_STARTWRN)
  	||(d > DTC_MAXNUM)
  	)
  {
  	
  }
  else
  {
     /* buffer for DTC data */
     TDTCBuf buf;
     /* collect U32 words separately to prevent mixup */
     U32 buf32[4];
     /* get additional data (application-defined function) */
     buf.lcode = GetDTCInfo((dtc & DTC_DTCMASK), buf.store.buf16, buf32);
     /* store dtc in first word */
     buf.dtc = (dtc & (DTC_DTCMASK|DTC_ACTMASK));
     /* add 32bit data to buffer; */
     pal_memcpy(&(buf.store.buf16[CNT16(buf.lcode)]), buf32, CNT32(buf.lcode) * 4U);
     /* post request to queue */
	 BO ret = requestStoreActiveCodeToHist_dsc((const TDTCBuf *)(&buf));
	 
     if(TRUE != Is_TrueOrFalse(ret))
     {
	 	/* MISAC */
	 }
  }
}

void ErrCheck(U16 dtc, BO active)
{
    if(Is_TrueOrFalse(kwpservices_get_passive_mode()) )
    {
		
    }
	else
	{
	    activeDtcTrigger_Result activeDtcReport = activeDtcTrigger(dtc,active);

	    if( (ACTIVEDTC_ADD == activeDtcReport) || (ACTIVEDTC_DECREASE == activeDtcReport) )
	    {
	        flag_has_dtc_changes = TRUE;
	    }

	    if(ACTIVEDTC_ADD == activeDtcReport)
	    {
	        QPostDTC(dtc);
	    }
	}

}

#if 0 //2020-06-01 comment unUsed API
/* this is for DTC RANGE [0,99] */
dtcTrigger_Result kwp_dtc_trigger(U16 dtc_code,BO active)
{
    activeDtcTrigger_Result activeDtcReport = ACTIVEDTC_NO_CHANGE;

    TDTCBuf buf;
    pal_memzero(&buf, sizeof(buf) );    
    buf.dtc = (dtc_code & (DTC_DTCMASK|DTC_ACTMASK));


    if( kwpservices_get_passive_mode() )    /* TBD  */
    {
        return TriggerReject;
    }
    activeDtcReport = activeDtcTrigger( dtc_code, active);

    if( (ACTIVEDTC_ADD == activeDtcReport) || (ACTIVEDTC_DECREASE == activeDtcReport) )
    {
        flag_has_dtc_changes = TRUE;
    }

    if(ACTIVEDTC_ADD == activeDtcReport)
    {
        if(requestStoreActiveCodeToHist_dsc(&buf))
        {
			return TriggerActiveAndHist;	
		}
    }
    return TriggerActive;
}
/* this is for DTC RANGE [100,199] */
dtcTrigger_Result kwp_dtc_trigger_with_one_s16_extra(U16 dtc_code, BO active, S16 ext1)
{
    activeDtcTrigger_Result activeDtcReport = ACTIVEDTC_NO_CHANGE;

    TDTCBuf buf;
    pal_memzero(&buf, sizeof(buf) );    
    buf.dtc = (dtc_code & (DTC_DTCMASK|DTC_ACTMASK));
    buf.store.buf16[0] = (U16)ext1;

    if( kwpservices_get_passive_mode() )    /* TBD  */
    {
        return TriggerReject;
    }
    activeDtcReport = activeDtcTrigger( dtc_code, active);

    if( (ACTIVEDTC_ADD == activeDtcReport) || (ACTIVEDTC_DECREASE == activeDtcReport) )
    {
        flag_has_dtc_changes = TRUE;
    }

    if(ACTIVEDTC_ADD == activeDtcReport)
    {
        if(requestStoreActiveCodeToHist_dsc(&buf))
        {
			return TriggerActiveAndHist;	
		}
    }
	
    return TriggerActive;
}

/* this is for DTC RANGE [200,999] with_fourS16_twoF32_extra*/
dtcTrigger_Result kwp_dtc_trigger_with_fourS16_twoF32_extra(U16 dtc_code, BO active,S16 ext1_s16,S16 ext2_s16,F32 ext3_s16,F32 ext4_s16, F32 ext5_f32,F32 ext6_f32)
{
    activeDtcTrigger_Result activeDtcReport = ACTIVEDTC_NO_CHANGE;

    TDTCBuf buf;
    pal_memzero(&buf, sizeof(buf) );    
    buf.dtc = (dtc_code & (DTC_DTCMASK|DTC_ACTMASK));
    U8 has_s16 = 4; // n1
    U8 has_f32 = 2; // n2
    U8 length1 = (has_f32 << 4) | has_s16;
    buf.lcode  = (U16)((0<<8) | length1);
    buf.store.buf16[0] = ext1_s16;
    buf.store.buf16[1] = ext2_s16;
    buf.store.buf16[2] = ext3_s16;
    buf.store.buf16[3] = ext4_s16;
    buf.store.floatbuf[2] = ext5_f32;
    buf.store.floatbuf[3] = ext6_f32;
    
    if( kwpservices_get_passive_mode() )    /* TBD  */
    {
        return TriggerReject;
    }
    activeDtcReport = activeDtcTrigger( dtc_code, active);

    if( (ACTIVEDTC_ADD == activeDtcReport) || (ACTIVEDTC_DECREASE == activeDtcReport) )
    {
        flag_has_dtc_changes = TRUE;
    }

    if(ACTIVEDTC_ADD == activeDtcReport)
    {
        if(requestStoreActiveCodeToHist_dsc(&buf))
        {
			return TriggerActiveAndHist;	
		}
    }

    return TriggerActive;
}

/* this is for DTC RANGE [200,999]  with_four_f32_extra*/
dtcTrigger_Result kwp_dtc_trigger_with_four_f32_extra(U16 dtc_code, BO active, F32 ext1,F32 ext2,F32 ext3, F32 ext4)
{
    activeDtcTrigger_Result activeDtcReport = ACTIVEDTC_NO_CHANGE;

    TDTCBuf buf;
    pal_memzero(&buf, sizeof(buf) );    
    buf.dtc = (dtc_code & (DTC_DTCMASK|DTC_ACTMASK));
    U8 has_s16 = 0; // n1
    U8 has_f32 = 4; // n2
    U8 length1 = (has_f32 << 4) | has_s16;
    buf.lcode  = (U16)((0<<8) | length1);
    buf.store.floatbuf[0] = ext1;
    buf.store.floatbuf[1] = ext2;
    buf.store.floatbuf[2] = ext3;
    buf.store.floatbuf[3] = ext4;

    if( kwpservices_get_passive_mode() )    /* TBD  */
    {
        return TriggerReject;
    }
    activeDtcReport = activeDtcTrigger( dtc_code, active);

    if( (ACTIVEDTC_ADD == activeDtcReport) || (ACTIVEDTC_DECREASE == activeDtcReport) )
    {
        flag_has_dtc_changes = TRUE;
    }

    if(ACTIVEDTC_ADD == activeDtcReport)
    {
        if(requestStoreActiveCodeToHist_dsc(&buf))
        {
			return TriggerActiveAndHist;	
		}
    }
    return TriggerActive;
}
#endif
static U8 loadHistoryDTC_Type0(void)
{
    U16 head 		= 0;
	U8 	retCount 	= 0;
	
    //value range check
    if(stReadWriteParam.total_historydtc_type0 > MAX_TOTAL_HISTORYDTC_TYPE0)
    {
        U16 setValue = 0;    
		RC ret = RC_ERROR;
        ret = sd_write( NVRAM_SD,&(pDtcOperater->pop_historydtcindex_type0),  &setValue,2);
		if(RC_SUCCESS != ret)
		{
			
		}
        ret = sd_write( NVRAM_SD,&(pDtcOperater->push_historydtcindex_type0), &setValue,2);
		if(RC_SUCCESS != ret)
		{
			
		}
        ret = sd_write( NVRAM_SD,&(pDtcOperater->total_historydtc_type0),     &setValue,2);
		if(RC_SUCCESS != ret)
		{
			
		}

        stReadWriteParam.pop_historydtcindex_type0  = 0; 
        stReadWriteParam.push_historydtcindex_type0 = 0;
        stReadWriteParam.total_historydtc_type0     = 0;
        retCount = 0;
    }
	else
	{
	    U8 	i 		= 0;
	    for(i= 0;i < stReadWriteParam.total_historydtc_type0;i++)
	    {
			RC ret = RC_ERROR;
	        ret = sd_read( NVRAM_SD,&head, &(pDtcCodeList->dtc_history_type0[(stReadWriteParam.pop_historydtcindex_type0+i)%MAX_TOTAL_HISTORYDTC_TYPE0]), 2);
			if(RC_SUCCESS != ret)
			{
				
			}

			historyDtcBuffer_Type0[i] = head;
	    }
		retCount = stReadWriteParam.total_historydtc_type0;
	}

    return retCount;
}
static U8 loadHistoryDTC_Type1(void)
{
    U16 head = 0;
	U8 retCount = 0;
	
    //value range check
    if(stReadWriteParam.total_historydtc_type1 > MAX_TOTAL_HISTORYDTC_TYPE1)
    {
        U16 setValue = 0;  
		RC ret = RC_ERROR;
        ret = sd_write( NVRAM_SD,&(pDtcOperater->pop_historydtcindex_type1),  &setValue,2);
		if(RC_SUCCESS != ret)
		{
			
		}
        ret = sd_write( NVRAM_SD,&(pDtcOperater->push_historydtcindex_type1), &setValue,2);
		if(RC_SUCCESS != ret)
		{
		}
        ret = sd_write( NVRAM_SD,&(pDtcOperater->total_historydtc_type1),     &setValue,2);
		if(RC_SUCCESS != ret)
		{
		}
        stReadWriteParam.pop_historydtcindex_type1  = 0; 
        stReadWriteParam.push_historydtcindex_type1 = 0;
        stReadWriteParam.total_historydtc_type1     = 0;

        retCount = 0;
    }
	else
	{
		U8 i = 0;
	    for(i= 0;i < stReadWriteParam.total_historydtc_type1;i++)
	    {
			RC ret = RC_ERROR;
	        ret = sd_read( NVRAM_SD,&head,&(pDtcCodeList->dtc_history_type1_code[(stReadWriteParam.pop_historydtcindex_type1+i)%MAX_TOTAL_HISTORYDTC_TYPE1]), 2);
			if(RC_SUCCESS != ret)
			{
			}
			historyDtcBuffer_Type1[i] = head;
	    }
	    retCount = stReadWriteParam.total_historydtc_type1;
	}

	return retCount;
}
static U8 loadHistoryDTC_Type2(void)
{
    U16 head = 0;
	U8 retCount = 0;
	
    //value range check
    if(stReadWriteParam.total_historydtc_type2 > MAX_TOTAL_HISTORYDTC_TYPE2)
    {
        U16 setValue = 0;
        RC ret = RC_ERROR;
        ret = sd_write( NVRAM_SD,&(pDtcOperater->pop_historydtcindex_type2),  &setValue,2);
		if(RC_SUCCESS != ret)
		{
			
		}
        ret = sd_write( NVRAM_SD,&(pDtcOperater->push_historydtcindex_type2), &setValue,2);
		if(RC_SUCCESS != ret)
		{
			
		}
        ret = sd_write( NVRAM_SD,&(pDtcOperater->total_historydtc_type2),     &setValue,2);
		if(RC_SUCCESS != ret)
		{
			
		}
        stReadWriteParam.pop_historydtcindex_type2  = 0; 
        stReadWriteParam.push_historydtcindex_type2 = 0;
        stReadWriteParam.total_historydtc_type2     = 0;

        retCount = 0;
    }
	else
	{
		U8 i = 0;
	    for(i= 0;i < stReadWriteParam.total_historydtc_type2;i++)
	    {
			RC ret = RC_ERROR;
	        ret = sd_read( NVRAM_SD,&head,&(pDtcCodeList->dtc_history_type2_code[((stReadWriteParam.pop_historydtcindex_type2+i)%MAX_TOTAL_HISTORYDTC_TYPE2)]), 2);
			if(RC_SUCCESS != ret)
			{
				
			}
			historyDtcBuffer_Type2[i] = head;
	    }
	    retCount = stReadWriteParam.total_historydtc_type2;
	}

	return retCount;
}

void loadDTC_handlers(void)
{
    
}
void loadDtcHistoryInfomation(void)
{
	BO loadCount = 0;
    loadDTC_handlers();

	loadCount = loadHistoryDTC_Type0();
	if(loadCount > 0u)
	{
		
	}
    loadCount = loadHistoryDTC_Type1();
	if(loadCount > 0u)
	{
		
	}
    loadCount = loadHistoryDTC_Type2();
	if(loadCount > 0u)
	{
		
	}
}

void dtc_init(void)
{
    totalActive = 0;
    pushRequestIndex = 0;
    popRequestIndex = 0;
    flag_has_dtc_changes = FALSE;
    pal_memzero( &activeDTCbuffer, sizeof(activeDTCbuffer) );
    loadDtcHistoryInfomation();

    #if 0   /* example of manual-trigger DTC, do not swith-on below statement in release-version */
    kwp_dtc_trigger(99,TRUE);   /* [0,99] */
    kwp_dtc_trigger_with_one_s16_extra(199,TRUE,11);    /* [100, 199] */
    kwp_dtc_trigger_with_four_f32_extra(200, TRUE, 1, 2, 3, 4); /* [200, 999] */
    kwp_dtc_trigger_with_fourS16_twoF32_extra(201, TRUE,1 , 2, 3, 4, 5, 6); /* [200, 999] */
    #endif
}


BO getStoreHist_request(request_hist_dtc_st* myReq)
{
	BO ret = FALSE;
	
    if(RequestCount > 0u)
    {
        myReq->DTC = saveHistoryDtcRequestBuffer[(popRequestIndex)%DTC_HIST_REQ_BUF_SIZE].DTC;
        myReq->Length = saveHistoryDtcRequestBuffer[(popRequestIndex)%DTC_HIST_REQ_BUF_SIZE].Length;
        U8 copy_index = 0;
        for(copy_index = 0;copy_index < (DTC_TYPE2_EXTRA_SIZE/2u);copy_index++)
        {
            myReq->ExtraData[copy_index] =  saveHistoryDtcRequestBuffer[(popRequestIndex)%DTC_HIST_REQ_BUF_SIZE].ExtraData[copy_index];
        }
        popRequestIndex = (popRequestIndex+1u)%DTC_HIST_REQ_BUF_SIZE;
        --RequestCount;
        ret = TRUE;
    }
    
    return ret;
}


BO storeHistDtcType0(U16 codeNum)
{
    BO flag_dtc_already_exisit = FALSE;
    U8 i;
	BO ret_result = FALSE;
    
    for(i= 0;i < stReadWriteParam.total_historydtc_type0;i++)
    {
        if( (codeNum&DTCCODE_MASK) == (historyDtcBuffer_Type0[i]&DTCCODE_MASK) )
        {
            flag_dtc_already_exisit = TRUE;
            break;
        }
    }
    
    if(!flag_dtc_already_exisit)
    {
        if(stReadWriteParam.total_historydtc_type0 <= MAX_TOTAL_HISTORYDTC_TYPE0)
        {
			RC ret = RC_ERROR;
            if(stReadWriteParam.total_historydtc_type0 < MAX_TOTAL_HISTORYDTC_TYPE0)
            {
                ret = sd_write( NVRAM_SD,&(pDtcCodeList->dtc_history_type0[(stReadWriteParam.push_historydtcindex_type0)%MAX_TOTAL_HISTORYDTC_TYPE0]),&codeNum,2);
                if(RC_SUCCESS != ret)
                {
					
				}
                ++stReadWriteParam.push_historydtcindex_type0;
                ret= sd_write( NVRAM_SD,&(pDtcOperater->push_historydtcindex_type0),&stReadWriteParam.push_historydtcindex_type0,2);
                if(RC_SUCCESS != ret)
                {
					
				}
				++stReadWriteParam.total_historydtc_type0;
                ret = sd_write( NVRAM_SD,&(pDtcOperater->total_historydtc_type0), &stReadWriteParam.total_historydtc_type0,2);
                if(RC_SUCCESS != ret)
                {
					
				}
			}
            else
            {
                ret = sd_write( NVRAM_SD,&(pDtcCodeList->dtc_history_type0[(stReadWriteParam.push_historydtcindex_type0)%MAX_TOTAL_HISTORYDTC_TYPE0]),&codeNum,2);
                if(RC_SUCCESS != ret)
                {
					
				}
                ++stReadWriteParam.push_historydtcindex_type0;
                ret = sd_write( NVRAM_SD,&(pDtcOperater->push_historydtcindex_type0),&stReadWriteParam.push_historydtcindex_type0,2);
	            if(RC_SUCCESS != ret)
                {
					
				}
				++stReadWriteParam.pop_historydtcindex_type0;
                ret = sd_write( NVRAM_SD,&(pDtcOperater->pop_historydtcindex_type0),  &stReadWriteParam.pop_historydtcindex_type0,2);
	            if(RC_SUCCESS != ret)
                {
					
				}

			}
            U8 loadCount = loadHistoryDTC_Type0();
			if(loadCount >0u)
			{
				
			}
        }
        ret_result = TRUE;
    }

    return ret_result;
}
histDtcTrigger_Result historyDtcTrigger(void)
{
    histDtcTrigger_Result result = HISTDTC_STORE_FAIL;

    if(stReadWriteParam.total_historydtc_type0 > MAX_TOTAL_HISTORYDTC_TYPE0)
    {
        U16 setValue = 0;
        RC ret = RC_ERROR;
        ret = sd_write( NVRAM_SD,&(pDtcOperater->pop_historydtcindex_type0),  &setValue,2);
		if(RC_SUCCESS != ret)
		{

		}
        ret = sd_write( NVRAM_SD,&(pDtcOperater->push_historydtcindex_type0), &setValue,2);
		if(RC_SUCCESS != ret)
		{

		}
		ret = sd_write( NVRAM_SD,&(pDtcOperater->total_historydtc_type0),     &setValue,2);
		if(RC_SUCCESS != ret)
		{

		}
    }
	else if(stReadWriteParam.total_historydtc_type1 > MAX_TOTAL_HISTORYDTC_TYPE1)
    {
        U16 setValue = 0;
        RC ret = RC_ERROR;
        ret = sd_write( NVRAM_SD,&(pDtcOperater->pop_historydtcindex_type1),  &setValue,2);
		if(RC_SUCCESS != ret)
		{

		}
        ret = sd_write( NVRAM_SD,&(pDtcOperater->push_historydtcindex_type1), &setValue,2);
		if(RC_SUCCESS != ret)
		{

		}
        ret = sd_write( NVRAM_SD,&(pDtcOperater->total_historydtc_type1),     &setValue,2);
		if(RC_SUCCESS != ret)
		{

		}
    }
    else if(stReadWriteParam.total_historydtc_type2 > MAX_TOTAL_HISTORYDTC_TYPE2)
    {
        U16 setValue = 0;
        RC ret = RC_ERROR;
		
        ret = sd_write( NVRAM_SD,&(pDtcOperater->pop_historydtcindex_type2),      &setValue,2);
		if(RC_SUCCESS != ret)
		{

		}
        ret = sd_write( NVRAM_SD,&(pDtcOperater->push_historydtcindex_type2), &setValue,2);
		if(RC_SUCCESS != ret)
		{

		}
        ret = sd_write( NVRAM_SD,&(pDtcOperater->total_historydtc_type2),     &setValue,2);
		if(RC_SUCCESS != ret)
		{

		}
    }
	else
	{
	    request_hist_dtc_st processReq;
	    BO getReqSuccess = getStoreHist_request(&processReq);
	    //U8 i = 0;
    
	    if(Is_TrueOrFalse(getReqSuccess))
	    {
	        if( (processReq.DTC&DTCCODE_MASK) <= TYPE0_END)
	        {
	            if(Is_TrueOrFalse(storeHistDtcType0(processReq.DTC)) )
	            {
	                result = HISTDTC_STORE_SUCCESS;
	            }
	            else
	            {
	                result = HISTDTC_STORE_ALREADY_EXIST;
	            }
	        }
	        else if( (processReq.DTC&DTCCODE_MASK) <= TYPE1_END)
	        {
	            U16 dtcCode = processReq.DTC | ACTIVE_MASK;
	            
	            histDtcStatusType1_t info;
	            pal_memzero(&info,sizeof(histDtcStatusType1_t));
	            info.atom.TWT = time_diag_interface.Component_work_time;
	            info.atom.CWT = time_diag_interface.Component_work_time;
	            info.atom.DT  = input_data.ba_DateTime_Can;
	            info.atom.ExtraData = *((S16*)(&processReq.ExtraData));
	            
	            BO flag_dtc_already_exisit = FALSE;
				U8 i = 0;
	            for(i= 0;i < stReadWriteParam.total_historydtc_type1;i++)
	            {
	                if( (processReq.DTC&DTCCODE_MASK) == (historyDtcBuffer_Type1[i]&DTCCODE_MASK) )
	                {
	                    flag_dtc_already_exisit = TRUE;
	                    break;
	                }
	            }
	            
	            if(!flag_dtc_already_exisit)
	            {
					RC ret = RC_ERROR;
	                if(stReadWriteParam.total_historydtc_type1 < MAX_TOTAL_HISTORYDTC_TYPE1)
	                {
	                    ret = sd_write( NVRAM_SD,&(pDtcCodeList->dtc_history_type1_code[stReadWriteParam.push_historydtcindex_type1]),&dtcCode,2);
						if(RC_SUCCESS != ret)
						{

						}
						ret = sd_write( NVRAM_SD,&(pDtcStatusList->dtc_history_type1_status[stReadWriteParam.push_historydtcindex_type1]),&info,TYPE1_STATUS_LEN);
						if(RC_SUCCESS != ret)
						{

						}
	                    ++stReadWriteParam.push_historydtcindex_type1;
	                    ret = sd_write( NVRAM_SD,&(pDtcOperater->push_historydtcindex_type1),&stReadWriteParam.push_historydtcindex_type1,2);
						if(RC_SUCCESS != ret)
						{

						}
						++stReadWriteParam.total_historydtc_type1;
	                    ret = sd_write( NVRAM_SD,&(pDtcOperater->total_historydtc_type1), &stReadWriteParam.total_historydtc_type1,2);                    
						if(RC_SUCCESS != ret)
						{

						}
					}
	                else
	                {
	                    ret = sd_write( NVRAM_SD,&(pDtcCodeList->dtc_history_type1_code[stReadWriteParam.push_historydtcindex_type1]),&dtcCode,2);
						if(RC_SUCCESS != ret)
						{

						}
						ret = sd_write( NVRAM_SD,&(pDtcStatusList->dtc_history_type1_status[stReadWriteParam.push_historydtcindex_type1]),&info,TYPE1_STATUS_LEN);
						if(RC_SUCCESS != ret)
						{

						}
	                    ++stReadWriteParam.push_historydtcindex_type1;
	                    ret = sd_write( NVRAM_SD,&(pDtcOperater->push_historydtcindex_type1),&stReadWriteParam.push_historydtcindex_type1,2);
						if(RC_SUCCESS != ret)
						{

						}
						++stReadWriteParam.pop_historydtcindex_type1;
	                    ret = sd_write( NVRAM_SD,&(pDtcOperater->pop_historydtcindex_type1),  &stReadWriteParam.pop_historydtcindex_type1,2);                                     
						if(RC_SUCCESS != ret)
						{

						}
					}
	                U8 loadCount = loadHistoryDTC_Type1();
					if(loadCount > 0u)
					{
						
					}
	                
	                result = HISTDTC_STORE_SUCCESS;
	            }
	            else
	            {
	                result = HISTDTC_STORE_ALREADY_EXIST;
	            }
	            
	            
	        }
	        else if( (processReq.DTC&DTCCODE_MASK) <= TYPE2_END)
	        {
	            U16 dtcCode = processReq.DTC | ACTIVE_MASK;

	            histDtcStatusType2_t info;
	            pal_memzero(&info,sizeof(histDtcStatusType2_t));
	            info.atom.TWT = time_diag_interface.Component_work_time;
	            info.atom.CWT = time_diag_interface.Component_work_time;
	            info.atom.DT  = input_data.ba_DateTime_Can;
	            info.atom.Len1 = (U8)(processReq.Length&0x00FFu);
	            info.atom.Len2 = 0;

				U8 i = 0;
	            for(i = 0;i < (DTC_TYPE2_EXTRA_SIZE/2u);i++)
	            {
	                info.atom.ExtraData[i] = processReq.ExtraData[i];
	            }	            
	            
	            BO flag_dtc_already_exisit = FALSE;
	            for( i= 0;i < stReadWriteParam.total_historydtc_type2;i++)
	            {
	                if( (processReq.DTC&DTCCODE_MASK) == (historyDtcBuffer_Type2[i]&DTCCODE_MASK) )
	                {
	                    flag_dtc_already_exisit = TRUE;
	                    break;
	                }
	            }
	            
	            if(!flag_dtc_already_exisit)
	            {
					RC ret = RC_ERROR;
	                if(stReadWriteParam.total_historydtc_type2 < MAX_TOTAL_HISTORYDTC_TYPE2)
	                {
	                    ret = sd_write( NVRAM_SD,&(pDtcCodeList->dtc_history_type2_code[stReadWriteParam.push_historydtcindex_type2]),&dtcCode,2);
						if(RC_SUCCESS != ret)
						{

						}
						ret = sd_write( NVRAM_SD,&(pDtcStatusList->dtc_history_type2_status[stReadWriteParam.push_historydtcindex_type2]),&info,TYPE2_STATUS_LEN);
						if(RC_SUCCESS != ret)
						{

						}

	                    ++stReadWriteParam.push_historydtcindex_type2;
	                    ret = sd_write( NVRAM_SD,&(pDtcOperater->push_historydtcindex_type2),&stReadWriteParam.push_historydtcindex_type2,2);
						if(RC_SUCCESS != ret)
						{

						}
						++stReadWriteParam.total_historydtc_type2;
	                    ret = sd_write( NVRAM_SD,&(pDtcOperater->total_historydtc_type2), &stReadWriteParam.total_historydtc_type2,2);                                                            
						if(RC_SUCCESS != ret)
						{

						}
					}
	                else
	                {
	                    ret = sd_write( NVRAM_SD,&(pDtcCodeList->dtc_history_type2_code[stReadWriteParam.push_historydtcindex_type2]),&dtcCode,2);
						if(RC_SUCCESS != ret)
						{

						}
						ret = sd_write( NVRAM_SD,&(pDtcStatusList->dtc_history_type2_status[stReadWriteParam.push_historydtcindex_type2]),&info,TYPE2_STATUS_LEN);
						if(RC_SUCCESS != ret)
						{

						}
	                    ++stReadWriteParam.push_historydtcindex_type2;
	                    ret = sd_write( NVRAM_SD,&(pDtcOperater->push_historydtcindex_type2),&stReadWriteParam.push_historydtcindex_type2,2);
						if(RC_SUCCESS != ret)
						{

						}
						++stReadWriteParam.pop_historydtcindex_type2;
	                    ret = sd_write( NVRAM_SD,&(pDtcOperater->pop_historydtcindex_type2),  &stReadWriteParam.pop_historydtcindex_type2,2);                                                         
						if(RC_SUCCESS != ret)
						{

						}
	                }
	                U8 loadCount = loadHistoryDTC_Type2();
					if( loadCount > 0u)
					{
						
					}
	                result = HISTDTC_STORE_SUCCESS;
	            }
	            else
	            {
	                result = HISTDTC_STORE_ALREADY_EXIST;
	            }
	        }
			else
			{
				
			}
	    }
	}
    
    return result;
}

BO reset_dtcStorageHandler(void)
{
    RC result = TRUE;

    U16 setValue = 0;

    U8 len = 0;
    for(len = 0;len < MAX_TOTAL_HISTORYDTC_TYPE0;len++)
    {
        historyDtcBuffer_Type0[len] = 0;
    }
    for(len = 0;len < MAX_TOTAL_HISTORYDTC_TYPE1;len++)
    {
        historyDtcBuffer_Type1[len] = 0;
    }
    for(len = 0;len < MAX_TOTAL_HISTORYDTC_TYPE2;len++)
    {
        historyDtcBuffer_Type2[len] = 0;
    }

    if( sd_write( NVRAM_SD,&(pDtcOperater->pop_historydtcindex_type0),&setValue,2) != RC_SUCCESS)
    {
        result = FALSE;
    }
    if( sd_write( NVRAM_SD,&(pDtcOperater->push_historydtcindex_type0),&setValue,2) != RC_SUCCESS)
    {
        result = FALSE;
    }
    if( sd_write( NVRAM_SD,&(pDtcOperater->total_historydtc_type0),&setValue,2) != RC_SUCCESS)
    {
        result = FALSE;
    }


    if( sd_write( NVRAM_SD,&(pDtcOperater->pop_historydtcindex_type1),&setValue,2) != RC_SUCCESS)
    {
        result = FALSE;
    }
    if( sd_write( NVRAM_SD,&(pDtcOperater->push_historydtcindex_type1),&setValue,2) != RC_SUCCESS)
    {
        result = FALSE;
    }
    if( sd_write( NVRAM_SD,&(pDtcOperater->total_historydtc_type1),&setValue,2) != RC_SUCCESS)
    {
        result = FALSE;
    }

    if( sd_write( NVRAM_SD,&(pDtcOperater->pop_historydtcindex_type2),&setValue,2) != RC_SUCCESS)
    {
        result = FALSE;
    }
    if( sd_write( NVRAM_SD,&(pDtcOperater->push_historydtcindex_type2),&setValue,2) != RC_SUCCESS)
    {
        result = FALSE;
    }
    if( sd_write( NVRAM_SD,&(pDtcOperater->total_historydtc_type2),&setValue,2) != RC_SUCCESS)
    {
        result = FALSE;
    }

    stReadWriteParam.total_historydtc_type0 = 0;
    stReadWriteParam.total_historydtc_type1 = 0;
    stReadWriteParam.total_historydtc_type2 = 0;    

    stReadWriteParam.pop_historydtcindex_type0 = 0;
    stReadWriteParam.pop_historydtcindex_type1 = 0;
    stReadWriteParam.pop_historydtcindex_type2 = 0; 

    stReadWriteParam.push_historydtcindex_type0 = 0;
    stReadWriteParam.push_historydtcindex_type1 = 0;
    stReadWriteParam.push_historydtcindex_type2 = 0;    
    
    return result;
}

/* get at-most 4 DTC over 200 */
/* PDO 0x381 */
void getDtcListOver_200(U16 dtcList[])
{
	U8 i = 0;
	U8 dtcOver200_counter = 0;

	for(i = 0;i < ACTIVE_DTC_TOTAL_NUM;i++)
	{
		if( (activeDTCbuffer[i] & ACTIVE_MASK)
			&&((activeDTCbuffer[i] &DTCCODE_MASK) >= 200u)
			)
		{
			dtcList[dtcOver200_counter] = activeDTCbuffer[i]&DTCCODE_MASK;

			++dtcOver200_counter;
			if(4u == dtcOver200_counter)
			{
				break;
			}
		}
	}
}
/***********************************************************************************************************************
*                             Copyright 2017 Linde Material Handling. All rights reserved.                             *
***********************************************************************************************************************/
